//common event names
var SAVE_EVENT = 'save';
var CLEAR_EVENT = 'clear';
var SHOW_EVENT = 'show';
var LOAD_EVENT = 'load';
var CHANGE_EVENT = 'change';
var SELECT_EVENT = 'select';
var EXCEPTION_EVENT = 'exception';

//Returns low border date for application
function getStartDate(){
	var d = new Date();
	d.setYear(2011);
	d.setMonth(0);
	return d.getFirstDateOfMonth();
}

//Returns current date
function getCurrentDate(){
	return new Date();
}

// Returns first day of curretn month
function getFirstDayOfMonth(){
	var d = new Date();
	return d.getFirstDateOfMonth();
}

/*function for show error message alert*/
function showError(resp){
	var errorMessage = resp.message;
	if(Ext.isDefined(errorMessage) && errorMessage != null){
		Ext.Msg.alert(labels['failure.alert.title'], errorMessage);
	}else{
		Ext.Msg.alert(labels['failure.alert.title'], messages['message.error.server.invalid']);
	}
}

//create years array with previous current and next year
function createYearsArray(){
	var years = new Array();
	var year = null;
	var j = 0;
	for(var i=-2; i<=0; i++){
		year = new Array();
		year[0]=new Date().add(Date.YEAR, i).getFullYear();
		years[j]=year;
		j++;
	}
	return years;
};

//define custom text field
function defineFormTextField(){
	hf.widget.FormTextField = Ext.extend(Ext.form.TextField, {
		initComponent: function(config){
			Ext.apply(this, {
				xtype: 'textfield',
				allowBlank:false,
				minLength: 5,
				maxLength: 20
			});
			hf.widget.FormTextField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('form-text-field', hf.widget.FormTextField);
};

//define custom button for form
function defineFormButton(){
	hf.widget.FormButton = Ext.extend(Ext.Button, {
		constructor: function(config){
			 Ext.apply(this, config);
			 hf.widget.FormButton.superclass.constructor.apply(this, arguments);
			 this.addEvents(this.buttonEvent);
			 this.on('click', function(button, event) {button.fireEvent(this.buttonEvent, button, event);}); 
		}
	});
	//register custom x-type for this widget
	Ext.reg('form-button', hf.widget.FormButton);
};

function defineWidgets(){
	
	// custom Vtype for vtype:'fourSign'
	var fourSignTest = /^0.0000$/;
	Ext.apply(Ext.form.VTypes, {
	    //  vtype validation function
	    fourSign: function(val, field) {
	        return fourSignTest.test(val);
	    }
	});
	
	// custom Vtype for vtype:'twoSign'
	var twoSignTest = /^0.00$/;
	Ext.apply(Ext.form.VTypes, {
	    //  vtype validation function
	    twoSign: function(val, field) {
	        return twoSignTest.test(val);
	    }
	});
	
	hf.widget.IdHiddenField = Ext.extend(Ext.form.Hidden, {
		initComponent: function(config){
			Ext.apply(this, {
				name: indexes['id'], 
				value: FAKE_ID
			});
			hf.widget.IdHiddenField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('id-hidden-field', hf.widget.IdHiddenField);
	
	hf.widget.EnabledHiddenField = Ext.extend(Ext.form.Hidden, {
		initComponent: function(config){
			Ext.apply(this, {
				name: indexes['enabled'], 
				value: ENTITY_STATE_ENABLED
			});
			hf.widget.EnabledHiddenField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('enabled-hidden-field', hf.widget.EnabledHiddenField);
	
	hf.widget.ModelIdHiddenField = Ext.extend(Ext.form.Hidden, {
		initComponent: function(config){
			Ext.apply(this, {
				name: indexes['modelId'], 
				value: FAKE_ID
			});
			hf.widget.ModelIdHiddenField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('modelid-hidden-field', hf.widget.ModelIdHiddenField);
	
	hf.widget.CommunalDateField = Ext.extend(Ext.form.DateField, {
		initComponent: function(config){
			Ext.apply(this, {
				fieldLabel: labels['label.date'], 
				name: indexes['date'], 
				format: DATE_FORMAT, width: 130, 
				value: new Date(),
				maxValue: new Date()
			});
			hf.widget.CommunalDateField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('communal-date-field', hf.widget.CommunalDateField);
	
	hf.widget.IntegerNumberField = Ext.extend(Ext.form.NumberField, {
		initComponent: function(config){
			Ext.apply(this, {
				value: 0,
				allowNegative: false, 
				allowBlank: false, 
				allowDecimals: false,
		     	blankText: labels['label.value.empty']
			});
			hf.widget.IntegerNumberField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('integer-number-field', hf.widget.IntegerNumberField);

	hf.widget.DoubleNumberField = Ext.extend(Ext.form.NumberField, {
		initComponent: function(config){
			Ext.apply(this, {
				value: 0,	
				allowNegative: false, 
				allowBlank: false, 
				decimalPrecision: 2, 
				vtype: 'twoSign',
				blankText: labels['label.value.empty']
			});
			hf.widget.DoubleNumberField.superclass.initComponent.apply(this, arguments); 
		}
	});
	Ext.reg('double-number-field', hf.widget.DoubleNumberField);

	//define column for category description in categories grid
	hf.widget.column.ActionColumn = Ext.extend(Ext.grid.ActionColumn, {
		constructor: function(config) {
			Ext.apply(this, {
				id: 'actionColumnId',
            	header: labels['column.title.delete'],
				width: 60, 
				align: 'center',
				iconCls: 'icon-delete',
				fixed: true,
				resizable: false,
				sortable: false,
				hideable: false,
				menuDisabled: true,
				tooltip: qtips['qtips.column.delete']
        	});
        	hf.widget.column.ActionColumn.superclass.constructor.apply(this, arguments);
        	this.on('click', function(column, grid, rowIndex, event){
        		Ext.Msg.confirm('', messages['alert.message.deleterecord'], function(btn, text){
    				if (btn == Ext.MessageBox.buttonText.yes.toLowerCase()){
    					grid.deleteRecord(column, grid, rowIndex, event);
    				}
    			});	
        	});
		}
	});
	Ext.grid.Column.types['action-column'] = hf.widget.column.ActionColumn;

	//combo box for month
	hf.widget.MonthCombo = Ext.extend(Ext.form.ComboBox, {
		constructor: function(config) {
			Ext.apply(this, {
				store: {
					xtype: 'arraystore',
					fields: [
						{name: 'id', type: INTEGER},
       					{name: 'name', type: STRING}
       				],
					data: months
				},
				name: indexes['month'],
				fieldLabel: labels['label.month'],
				typeAhead: false, 
			   	forceSelection: true,
				triggerAction: 'all',
				editable: false,
				selectOnFocus: true,
			   	mode: 'local', 
		   		valueField: 'id', 
		   		displayField: 'name',
		   		width: 130, 
		   		value: new Date().getMonth()
			});
			hf.widget.MonthCombo.superclass.constructor.apply(this, arguments);
		}
	});
	Ext.reg('month-combo', hf.widget.MonthCombo);
	
	//combo box for years
	hf.widget.YearCombo = Ext.extend(Ext.form.ComboBox, {
		constructor: function(config) {
			Ext.apply(this, {
				store: {
					xtype: 'arraystore',
					fields: [{name: indexes['year'], type: INTEGER}],
					data: createYearsArray()
				},
				name: indexes['year'],
				fieldLabel: labels['label.year'],
				typeAhead: false, 
			   	forceSelection: true,
				triggerAction: 'all',
				editable: false,
				selectOnFocus: true,
			   	mode: 'local', 
		   		valueField: indexes['year'], 
		   		displayField: indexes['year'],
		   		width: 130, 
		   		value: new Date().getFullYear()
			});
			hf.widget.YearCombo.superclass.constructor.apply(this, arguments);
		}
	});
	Ext.reg('year-combo', hf.widget.YearCombo);
	
	hf.widget.TarifTypeCombo = Ext.extend(Ext.form.ComboBox, {
		constructor: function(config) {
			Ext.apply(this, {
				store: {
					xtype: 'arraystore',
					fields: [
						{name: 'id', type: INTEGER},
						{name: 'name', type: STRING}
					],
					data: config.dataArray
				},
				name: 'tarifType',
				allowBlank: false,
				blankText: labels['label.value.empty'],
				fieldLabel: labels['label.tarif.type'],
				typeAhead: false, 
			   	forceSelection: true,
				triggerAction: 'all',
				editable: false,
				selectOnFocus: true,
			   	mode: 'local', 
		   		valueField: 'id', 
		   		displayField: 'name',
		   		width: 130
			});
			hf.widget.TarifTypeCombo.superclass.constructor.apply(this, arguments);
		}
	});
	Ext.reg('tarif-type-combo', hf.widget.TarifTypeCombo);
	
	hf.widget.TarifCombo = Ext.extend(Ext.form.ComboBox, {
		constructor: function(config) {
			Ext.apply(this, {
				store: config.store,
				name: 'tarifId',
				ref: '../tarifCombo',
				fieldLabel: labels['label.tarif'],
				typeAhead: false,
				allowBlank: false,
				blankText: labels['label.value.empty'],
			   	forceSelection: true,
				triggerAction: 'all',
				editable: false,
				selectOnFocus: true,
			   	mode: 'local', 
		   		valueField: 'id', 
		   		displayField: 'tarifName',
		   		width: 130
			});
			hf.widget.TarifCombo.superclass.constructor.apply(this, arguments);
		}
	});
	Ext.reg('tarif-combo', hf.widget.TarifCombo);
	
	hf.widget.ChartPanel = Ext.extend(Ext.Panel, {
		constructor: function() {
			Ext.apply(this, {
				title: labels['label.chart.title'],
				anchor: '100% 60%', 
				frame: true,
				items: [{
					xtype: 'linechart',
					store: null,
					ref: '../../../statisticChart',
					xField: 'monthYear',
					yField: indexes['summa'],
					anchor: '100% 100%',
					yAxis: new Ext.chart.NumericAxis({
						labelRenderer: Ext.util.Format.numberRenderer('0.00')
					})
				}]
			});
			hf.widget.ChartPanel.superclass.constructor.apply(this, arguments);
		}
	});
	Ext.reg('chart-panel', hf.widget.ChartPanel);
	
	hf.data.AppStore = Ext.extend(Ext.data.Store, {
		constructor: function(config) {
			Ext.apply(this, {
				proxy:	new Ext.data.HttpProxy({
					api: {
						read : config.viewAction,
						create : config.addAction,
						update: config.updateAction,
						destroy: config.deleteAction
					},
					listeners: {
						exception: function(proxy, type, action, options, response) {
							showError(response);
						}
					}
				}),
				reader: new Ext.data.JsonReader({
		    	  	totalProperty: TOTAL_PROPERTY, 
		    	  	successProperty: SUCCSESS_PROPERTY,
		    	  	idProperty: indexes['id'], 
		    	  	root: ROOT, 
		    	  	messageProperty: MESSAGE_PROPERTY
		      	},config.columnArray),
		   	 	writer: new Ext.data.JsonWriter({ 
						encode: true, 
						writeAllFields: true 
				}),
		   	    remoteSort: false,
		        autoSync: true, 
		        autoLoad: false,
		        pruneModifiedRecords: true 
		  });
		  hf.data.AppStore.superclass.constructor.apply(this, arguments);
		  this.on('write', function(store, operation, result){
		  	this.reload();
		  });
		  this.on(EXCEPTION_EVENT, function(misc){
		  	this.rejectChanges();
		  	this.reload();
		  });
	   }	
    });
	Ext.reg('app-store', hf.data.AppStore);
	
	var FORM_ITEM_ID = 'formId';
	hf.widget.TarifWindow = Ext.extend(Ext.Window, {
		constructor: function(config) {
			Ext.apply(this, {
				title: labels['label.window.title'],
				layout:'fit',
				width:300,
				shadow: new Ext.Shadow({mode: 'drop'}),
				plain: true,
				modal: true,
				draggable: true,
					items: [{
						xtype: 'form',
						labelWidth: 130,
						itemId: FORM_ITEM_ID,
						frame: true,
						monitorValid: true,
						items: config.formItems,
						buttons:[{xtype: 'form-button', ref: '../../clearButton', text: labels['clear.button.label'], iconCls: 'icon-clear', buttonEvent: CLEAR_EVENT, tooltip: qtips['qtips.button.clear']}, 
							     {xtype: 'form-button', ref: '../../saveButton', text: labels['button.title.save'], iconCls: 'icon-save', buttonEvent: SAVE_EVENT, formBind: true, tooltip: qtips['qtips.tarif.save']}]	
					}]
			});
			hf.widget.TarifWindow.superclass.constructor.apply(this, arguments);
			
			this.on(SAVE_EVENT, function(button, event){
				this.saveRecord();
			});
    		this.on(CLEAR_EVENT, function(button, event){
    			this.clearData();
    		});
		    this.on(SHOW_EVENT, function(){
		    	this.loadData();
		    });
		    
			this.relayEvents(this.clearButton, [CLEAR_EVENT]);
			this.relayEvents(this.saveButton, [SAVE_EVENT]);
		},
		
		//load data from grid record after window appear
		loadData: function(){
			if(this.record == null){
	    		this.getComponent(FORM_ITEM_ID).getForm().reset();
	    	}else{
	    		this.getComponent(FORM_ITEM_ID).getForm().loadRecord(this.record);
	    	}	
		},
		
		//persist record to store and close window 
		saveRecord: function(){
			if(this.prepareSaving()){
				if(Ext.isDefined(this.grid) && this.grid != null){
					if(this.record == null){
						var store = this.grid.getStore();
		    			this.record = new store.recordType(store.defaultData, FAKE_ID);
					}
					this.getComponent(FORM_ITEM_ID).getForm().updateRecord(this.record);
					if(this.record.id == FAKE_ID){
						this.grid.getStore().insert(0, this.record);
					}
				}
				this.record = null;
				this.close();
			}
		},
		
		//calls before record saving
		//can be used for validation
		prepareSaving: function(){
			return true;
		},
		
		//clear all inputed values
		clearData: function(){
			this.getComponent(FORM_ITEM_ID).getForm().reset();
		}
		
	});
	Ext.reg('tarif-window', hf.widget.TarifWindow);
	
	hf.widget.CommunalWindow = Ext.extend(Ext.Window, {
		constructor: function(config) {
			Ext.apply(this, {
				title: labels['label.window.title'],
				layout:'fit',
				width:300,
				shadow: new Ext.Shadow({mode: 'drop'}),
				plain: true,
				modal: true,
				draggable: true,
					items: [{
						xtype: 'form',
						labelWidth: 130,
						itemId: FORM_ITEM_ID,
						frame: true,
						monitorValid: true,
						items: config.formItems,
						buttons:[{xtype: 'form-button', ref: '../../clearButton', text: labels['clear.button.label'], iconCls: 'icon-clear', buttonEvent: CLEAR_EVENT, tooltip: qtips['qtips.button.clear']}, 
							     {xtype: 'form-button', ref: '../../saveButton', text: labels['button.title.save'], iconCls: 'icon-save', buttonEvent: SAVE_EVENT, formBind: true, tooltip: qtips['qtips.tarif.save']}]	
					}]
			});
			hf.widget.CommunalWindow.superclass.constructor.apply(this, arguments);
			
			this.on(SAVE_EVENT, function(button, event){
    			this.saveRecord();
    		});
    		
    		this.on(CLEAR_EVENT, function(button, event){
    			this.clearData();
    		});
    		
		    this.on(SHOW_EVENT, function(){
		    	this.tarifCombo.getStore().load();
		    });
		    
		    this.on(LOAD_EVENT, function(){
		    	this.loadData();
		    });
		    
		    this.on(CHANGE_EVENT, function(){
		    	this.calculateSumma();
		    });
		    
		    this.on(SELECT_EVENT, function(){
		    	this.calculateSumma();
		    });
		    
		    this.relayEvents(this.tarifCombo.getStore(), [LOAD_EVENT]);
		    this.relayEvents(this.tarifCombo, [SELECT_EVENT]);
		    
		    this.relayEvents(this.clearButton, [CLEAR_EVENT]);
		    this.relayEvents(this.saveButton, [SAVE_EVENT]);
		},
		
		loadData: function(){
		   	var newRecordFlag = false;
	    	if(this.record == null){
	    		newRecordFlag = true;
	    		this.clearData();
	    	}else{
	    		this.getComponent(FORM_ITEM_ID).getForm().loadRecord(this.record);
	    	}
	    	if(newRecordFlag){
	    		this.calculateSumma();
	    	}
		},
		
		saveRecord: function(){
			if(Ext.isDefined(this.grid) && this.grid != null){
				if(this.record == null){
					var store = this.grid.getStore();
		    		this.record = new store.recordType(store.defaultData, FAKE_ID);
				}
				this.getComponent(FORM_ITEM_ID).getForm().updateRecord(this.record);
				if(this.record.id == FAKE_ID){
					this.grid.getStore().insert(0, this.record);
				}
			}
			this.close();
		},
		
		clearData: function(){
			this.getComponent(FORM_ITEM_ID).getForm().reset();
		},
		
		//calculate summa when tarif changes
		calculateSumma: function(){
			var selectTarifId = this.tarifCombo.getValue();
			var tarif = this.tarifCombo.getStore().getById(selectTarifId);
			if(tarif != null){
				this.summaField.setValue(tarif.data.summa);
			}	
		}
	});
	Ext.reg('communal-window', hf.widget.CommunalWindow);
	
	hf.widget.AppGrid = Ext.extend(Ext.grid.GridPanel, {
		constructor: function(config) {
			 Ext.apply(this, {
				title: labels['label.tariff.grid.title'],
         		selModel: new Ext.grid.RowSelectionModel({
         			singleSelect: true,
         			listeners: {
         				'rowselect': function(selectionModel, rowIndex, record){
         					if(selectionModel.grid.getStore().getTotalCount() == 1){
         						selectionModel.deselectRow(rowIndex);
         					}
         					var w = config.windowType;
         					w.grid = selectionModel.grid;
         					w.record = record;
         					Ext.create(w).show();
         				}
         			}
         		}),
	       		viewConfig: {autoFill: true, forceFit: true},
	       		frame: true,
	       		columnLines: true,
	       		stripeRows: true		
		    });
		    Ext.applyIf(this, {
		    	tbar: [{xtype: 'form-button', ref: '../addButton', iconCls: 'icon-add', text: labels['button.title.add'], 
		    		buttonEvent: 'addRecord', tooltip: qtips['qtips.button.tarif.add']}]
		    });
		    hf.widget.AppGrid.superclass.constructor.apply(this, arguments);
		    this.addEvents('deleteRecord');
		    
		    this.on('addRecord', function(button, event) {
		    	var w = config.windowType;
         		w.grid = this;
         		w.record = null;
         		Ext.create(w).show();
			});
			
			this.relayEvents(this.addButton, ['addRecord']);
	    },
	    deleteRecord: function(column, grid, rowIndex, event){
	    	grid.getStore().remove(grid.getStore().getAt(rowIndex));	
	    },
		loadData: function(){
			this.getStore().load();
		}
	});
	Ext.reg('app-grid', hf.widget.AppGrid);
	
	hf.widget.CommunalGrid = Ext.extend(hf.widget.AppGrid, {
		constructor: function(config) {
			Ext.apply(this, {
	       		tbar: [
	       			{xtype: 'form-button', ref: '../addButton', iconCls: 'icon-add', text: labels['button.title.add'], buttonEvent: 'addRecord', tooltip: qtips['qtips.button.tarif.add']},
	       			{xtype: 'tbseparator'},
	       			{xtype: 'form-button', ref: '../showAllButton', iconCls: 'icon-show-all', 
	       				text: labels['button.title.showall'], buttonEvent: 'showAll', tooltip: qtips['qtips.button.showall']},
	       			{xtype: 'tbseparator'},
	       			{xtype: 'tbspacer', width: 3},
	       			{xtype: 'tbtext', text: labels['label.year']},
	       			{xtype: 'tbspacer', width: 3},
	       			{xtype: 'year-combo', ref: '../yearCombo', value: '-'},
	       			{xtype: 'tbspacer', width: 10},
	       			{xtype: 'tbtext', text: labels['label.month']},
	       			{xtype: 'tbspacer', width: 3},
	       			{xtype: 'month-combo', ref: '../monthCombo', value: '-'},
	       			{xtype: 'tbseparator'}]
		    });
		    hf.widget.CommunalGrid.superclass.constructor.apply(this, arguments);
		    
		    this.on(SELECT_EVENT, function(field, newValue, oldValue){
		    	this.loadData();
		    });
		    
		    this.on('showAll', function(button, event){
		    	this.yearCombo.setValue('-');
		    	this.monthCombo.setValue('-');
		    	this.loadData();
		    });
		    
		    this.relayEvents(this.showAllButton, ['showAll']);
		    this.relayEvents(this.yearCombo, [SELECT_EVENT]);
		    this.relayEvents(this.monthCombo, [SELECT_EVENT]);
	    },
	    
		loadData: function(){
			var year = this.yearCombo.getValue();
			if(year == '' || year == '-'){
				year = FAKE_ID; 
				this.yearCombo.setValue('-');
			}
			var month = this.monthCombo.getValue();
			if(month == '' || month == '-'){
				month = FAKE_ID; 
				this.monthCombo.setValue('-');
			}
			this.getStore().load({params: {year: year, month: month}});
		}
	});
	Ext.reg('communal-grid', hf.widget.CommunalGrid);
	
	
	hf.widget.AppTab = Ext.extend(Ext.Panel, {
		constructor: function(config) {
			Ext.apply(this, {
				layout: 'anchor'
	    	});
	    	hf.widget.AppTab.superclass.constructor.apply(this, arguments);
	    	this.on('activate', function(tab) {
	    		this.tarifGrid.loadData();
	    		this.recordGrid.loadData();
	    		this.statisticChart.bindStore(this.recordGrid.getStore());
	    	});
	    	this.on(LOAD_EVENT, function(store, records, options){
	    		if(store.getTotalCount() == 0){
	    			this.recordGrid.addButton.disable();
	    		}else{
	    			this.recordGrid.addButton.enable();
	    		}
	    	});
	    	this.relayEvents(this.tarifGrid.getStore(), [LOAD_EVENT]);
    	}	
	});
	Ext.reg('app-tab', hf.widget.AppTab);
};